'use strict';

const path = require('path');
const fs = require('fs');
const url = require('url');
const express = require('express');
const multer = require('multer');
const mime = require('mime');

const uploadHtml = `
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>文件上传</title>
    </head>
    <body>
        <h3>文件上传：</h3>
        选择一个文件上传: <br />
        <form action="/mmyyupload" method="post" enctype="multipart/form-data">
            <input type="file" name="file" />
            <input type="submit" value="上传" />
        </form>
    </body>
</html>`;

/*
* opt.port = 8081;
* opt.root = D:\workspace_node\www
* opt.plusIndex = 0-yesAndNoDir(normal), 1-yesAndShowDir, 2-neverAndShowDir
* opt.plusDemo = index.html
*/
var createWebStaticSrv = function (opt, callback) {
    if (!opt || !opt.root) {
        console.log("createWebStaticSrv error");
        callback(false, null, "");
        return null;
    }

    var idx = 0;
    var port = opt.port || 8081;
    var root = path.normalize(opt.root);
    var plusIndex = opt.plusIndex || 0;// 0 is false, and 0
    var plusDemo = opt.plusDemo || "index.html";

    function getClientIp(req) {
        return req.headers['x-forwarded-for'] ||
            req.connection.remoteAddress ||
            req.socket.remoteAddress ||
            req.connection.socket.remoteAddress;
    };

    function onFsFail(req, res, str) {
        res.setHeader("Content-Type", "text/html;charset=utf-8");
        res.end(`<h2>${decodeURIComponent(req.urlObj.url)}</h2><h3>msg: ${str}</h3>`);
    }

    function logResult(ori, result) {
        console.log(ori + result);
    }

    var app = express();
    app.use(function (req, res, next) {
        idx++;
        let thisIdx = idx;
        req.thisIdx = thisIdx;
        // host = hostname + port, path = pathname + search(? + query)
        let time = new Date().toTimeString();
        let logstr = `[no.${thisIdx}] [${time}] [${req.method}] [${decodeURIComponent(req.url)}] `;
        req.urlObj = url.parse(req.url);
        req.urlObj.url = req.url;
        let urlPath = decodeURI(req.urlObj.pathname);
        let filePath = path.join(root, urlPath);
        fs.stat(filePath, (err, fd) => {
            if (err) {
                // 假目录，假文件，或失败了
                if (req.url == '/mmyyupload') {
                    next();
                } else if (req.url == '/mmyyupload.html') {
                    res.setHeader("Content-Type", "text/html;charset=utf-8");
                    res.end(uploadHtml);
                } else {
                    onFsFail(req, res, "can not find file or dir");
                    logResult(logstr, "fail");
                }
                return;
            }
            let isDir = fd.isDirectory();
            if (!isDir) {
                // 非文件夹
                next();
                logResult(logstr, "succ");
                return;
            }
            // must be dir
            let tempIndexFile = path.join(filePath, plusDemo);
            let isIndexExists = fs.existsSync(tempIndexFile);
            if (plusIndex === 2 || (plusIndex === 1 && !isIndexExists)) {
                // 2-总是显示目录
                // 1-不存在index.html显示目录
                fs.readdir(filePath, (err, files) => {
                    if (!err) {
                        res.setHeader("Content-Type", "text/html;charset=utf-8");
                        let html = `<ul>`;
                        files.forEach((file, index, arr) => {
                            let uurrll = path.join(urlPath, file);
                            html += `<li><a href='${uurrll}'>${uurrll}</a></li>`;
                        });
                        html += "</ul>";
                        if (files.length == 0) {
                            html += "<p>nothing find in this dir</p>";
                        }
                        res.end(html);
                        logResult(logstr, "succ");
                    } else {
                        onFsFail(req, res, "read dir fail");
                        logResult(logstr, "fail");
                    }
                });
            } else {
                // 0,1-尽量显示index.html
                // 0-不存在index.html则forbidden
                if (isIndexExists) {
                    fs.readFile(tempIndexFile, (err, data) => {
                        if (!err) {
                            res.setHeader("Content-Type", mime.getType(tempIndexFile));
                            res.end(data);
                            logResult(logstr, "succ");
                        } else {
                            onFsFail(req, res, "read file fail");
                            logResult(logstr, "fail");
                        }
                    });
                } else {
                    onFsFail(req, res, "forbidden dir");
                    logResult(logstr, "succ");
                }
            }
        });
    });
    var uploadDir = path.join(root, '.');
    app.use(express.static(root));
    app.post('/mmyyupload', multer({
        //设置文件存储路径
        dest: uploadDir
    }).single('file'), function (req, res, next) {
        if (req.file.length === 0) {
            res.setHeader("Content-Type", "text/html;charset=utf-8");
            res.end("filename is null");
        } else {
            let file = req.file;
            console.log(file);
            fs.renameSync(path.join(uploadDir, file.filename), path.join(uploadDir, file.originalname));
            res.setHeader("Content-Type", "text/html;charset=utf-8");
            res.end("upload succ：" + path.join(uploadDir, file.originalname));
        }
    });
    app.use(function (req, res, next) {
        onFsFail(req, res, "something error.");
    });

    var server = null;
    try {
        server = app.listen(port, () => {
            console.log("createWebStaticSrv succ.");
            callback(true, server, `localhost:${port}`);
        });
    } catch (error) {
        server = null;
        console.log(error);
        callback(false, null, "");
    }
    return server;
};

module.exports = createWebStaticSrv;
